#ifndef _Sampler_H_
#define _Sampler_H_

#pragma once
#include "LightingRender.h"
#include <algorithm>

class Sampler {
protected:
	int numSamples, numSets;
	Vector2s samples;
	Vector2s diskSamples;
	Vector3s hemisphereSamples;
	Vector3s sphereSamples;
	Ints shuffledIndices;
	UInt count = 0;
	int jump = 0;

	virtual void generateSamples() = 0; // generate sample patterns in a unit square
	void setupShuffledIndices();

	void shuffle_X_Coordinates();
	void shuffle_Y_Coordinates();

	inline void nextSampleSetIfNeeded() {
		if (count % numSamples == 0)
			jump = (RANDINT % numSets) * numSamples;
	}
	inline int getSampleSet(int setIndex) {
		return (setIndex % numSets) * numSamples;
	}

public:
	Sampler(int numSamples, int numSets = 23) : numSamples(MathUtils::cutToSqrt(numSamples)), numSets(numSets) {}
	virtual ~Sampler() {}

	void setupSamples();

	void tentFilter();
	void cubicFilter();

	void mapSamplesToUnitDisk();
	void mapSamplesToHemisphere(Double exp);
	void mapSamplesToSqhere();

	Vector2 sampleUnitSquare();
	Vector2 sampleUnitDisk();
	Vector3 sampleHemisphere();
	Vector3 sampleSqhere();
	Vector2 sampleOneSet();

	Vector2 sampleUnitSquare(int setIndex, int sampleIndex);
	Vector2 sampleUnitDisk(int setIndex, int sampleIndex);
};

#endif // _Sampler_H_